﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main1(){
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);//&a 取出数组地址 +1跳过整个数组
	printf("%d,%d", *(a + 1), *(ptr - 1));
	return 0;
}





//在X86环境下假设结构体的⼤⼩是20个字节
//程序输出的结果是啥？
struct Test{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
 }*p = (struct Test*)0x100000;
//结构体指针struct Test* 

int main2()
 {
	//指针加减整数
	 printf("%p\n", p + 0x1);//指针+1,0x100000（十六进制）+20(十进制)
	 printf("%p\n", (unsigned long)p + 0x1);
	 //整数加整数 0x100000+1
	 printf("%p\n", (unsigned int*)p + 0x1);
	 //结构体指针强转成为int类型指针，指针+1只加sizeof(unsigned int)大小
	 //指针运算的步长由其指向的数据类型的大小决定
	 return 0;
 }




int main3()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };//逗号表达式
	int* p;
	p = a[0];//取第一行数组首元素的地址
	printf("%d", p[0]);//p[0]==*(p+0) 得到数组第一个元素
	return 0;
}


//假设环境是x86环境，程序输出的结果是啥
int main4()
{
	int a[5][5];
	int(*p)[4];//数组指针
	p = a; //a的类型int(*)[5](等于指针时) p和a有类型差距
	//p[4][2] == *(*(p+4)+2)
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
	//%p会将 -4 的补码当作地址输出（在32位下是 0xFFFFFFFC）
	return 0;
}




int main5()
{
	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int* ptr1 = (int*)(&aa + 1);
	//&aa属于特殊情况，取出整个数组的地址
	int* ptr2 = (int*)(*(aa + 1));
	//也可以这样：*(aa + 1)==aa[1] 数组名代表首元素地址
	//aa是数组名，是第一行数组的数组名，所以跳过第一行数组
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}





int main6()
{
	char* a[] = { "work","at","alibaba" };
	//char* p="acbasad";p存放的是这个字符串的首地址
	//所以当有多个字符串时，也可以使用指针数组来存放多个字符串的首地址
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	//pa是存放char* 的地址，那么* pa应该是得到char*
	//也就是指向at字符串的地址，%s可以使用地址直接打印字符串
	return 0;
}




int main7()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	//存放字符串首元素地址
	char** cp[] = { c + 3,c + 2,c + 1,c };
	//存放指向字符串的地址的地址
	char*** cpp = cp;
	//存放指向字符串的地址的地址的地址

	printf("%s\n", **++cpp);
	//指向第二个元素c+2的地址,解引用得到元素c+2，解引用得到POINT元素
	//的地址，打印的就是POINT

	printf("%s\n", *-- * ++cpp + 3);
	//+法优先级较低，最后算，* ++cpp拿到指针变量c+1,
	//--(c+1)得到c，指向ENTER字符地址，类型是char*，所以+3得到ER

	printf("%s\n", *cpp[-2] + 3);
	//cpp[-2]得到c+3内容，*(c+3)找到FIRST字符串地址，再+3得到ST

	printf("%s\n", cpp[-1][-1] + 1);
	//*(cpp-1)得到c+2的内容，c+2-1得到c+1，*(c+1)得到NEW字符串地址
	//+1得到EW 

	return 0;
}